package com.funtl.screw.common.datasource;

import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.creator.druid.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.processor.DsHeaderProcessor;
import com.baomidou.dynamic.datasource.processor.DsProcessor;
import com.baomidou.dynamic.datasource.processor.DsSessionProcessor;
import com.baomidou.dynamic.datasource.processor.DsSpelExpressionProcessor;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.funtl.screw.common.datasource.config.ClearTtlDsConfiguration;
import com.funtl.screw.common.datasource.config.DruidDataSourceProperties;
import com.funtl.screw.common.datasource.config.JdbcDynamicDataSourceProvider;
import com.funtl.screw.common.datasource.config.LastParamDsProcessor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Lusifer
 * @since 2023-02-06
 * <p>
 * 动态数据源切换配置
 */
@Configuration
@RequiredArgsConstructor
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(DruidDataSourceProperties.class)
public class DynamicDataSourceAutoConfiguration {

    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider(DefaultDataSourceCreator defaultDataSourceCreator,
                                                               DruidDataSourceProperties properties) {
        return new JdbcDynamicDataSourceProvider(defaultDataSourceCreator, properties);
    }

    @Bean
    public DsProcessor dsProcessor(BeanFactory beanFactory) {
        DsProcessor lastParamDsProcessor = new LastParamDsProcessor();
        DsProcessor headerProcessor = new DsHeaderProcessor();
        DsProcessor sessionProcessor = new DsSessionProcessor();
        DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
        spelExpressionProcessor.setBeanResolver(new BeanFactoryResolver(beanFactory));
        lastParamDsProcessor.setNextProcessor(headerProcessor);
        headerProcessor.setNextProcessor(sessionProcessor);
        sessionProcessor.setNextProcessor(spelExpressionProcessor);
        return lastParamDsProcessor;
    }

    @Bean
    public DefaultDataSourceCreator defaultDataSourceCreator(DruidDataSourceCreator druidDataSourceCreator) {
        DefaultDataSourceCreator defaultDataSourceCreator = new DefaultDataSourceCreator();
        List<DataSourceCreator> creators = new ArrayList<>();
        creators.add(druidDataSourceCreator);
        defaultDataSourceCreator.setCreators(creators);
        return defaultDataSourceCreator;
    }

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new ClearTtlDsConfiguration();
    }

}
